#include <iostream>
#include <string>
#include <cstring>

using namespace std;

class String
{
	public:
		char* p;

		String(string str="")
		{
			int idx = 0, len = str.length();
			p = new char[len+1];
			strcpy(p, str.c_str());
		}

		~String()
		{
			delete[] p;
		}

		String(const String& target)
		{
			p = new char[strlen(target.p)+1];
			strcpy(p, target.p);
		}

		size_t Length()
		{
			return strlen(p);
		}

		// Compare by string's dictionary sort.
		// Especially: abc < abcd
		// *this  <  target  -->  -1
		// *this  == target  -->   0
		// *this  >  target  -->   1
		int compareWith(const String& target)
		{
			int idx = 0;
			for (; p[idx] != '\0' && target.p[idx] != '\0'; idx += 1)
			{
				if (p[idx] < target.p[idx])
				{
					return -1;
				}
				else if (p[idx] > target.p[idx])
				{
					return 1;
				}
			}
			if (p[idx] == '\0' && target.p[idx] == '\0')
			{
				return 0;
			}
			else if (p[idx] == '\0')
			{
				return -1;
			}
			else
			{
				return 1;
			}
		}

		String& operator=(const String& target)
		{
			delete[] p;
			p = new char[strlen(target.p)+1];
			strcpy(p, target.p);
			return *this;
		}
		
		String& operator=(string target)  // Parameter type is string, don't use string&.
		{
			return operator=(String(target));
		}

		String operator+(const String& target)
		{
			String rtn;
			delete rtn.p;
			rtn.p = new char[strlen(p)+strlen(target.p)+1];
			strcpy(rtn.p, p);
			strcat(rtn.p, target.p);
			return rtn;
		}

		String& operator+=(const String& target)
		{
			*this = String(*this) + String(target);
			return *this;
		}

		char& operator[](const int idx)  // Return char&, not char.
		{
			return p[idx];
		}

		bool operator<(const String& target)
		{
			if (compareWith(target) == -1)
			{
				return true;
			}
			return false;
		}

		bool operator==(const String& target)
		{
			if (compareWith(target) == 0)
			{
				return true;
			}
			return false;
		}

		bool operator>(const String& target)
		{
			if (compareWith(target) == 1)
			{
				return true;
			}
			return false;
		}
};

istream& operator>>(istream& input, String& str)
{
	string tmp;
	input >> tmp;
	str = String(tmp);
	return input;
}

ostream& operator<<(ostream& output, const String& str)
{
	output << str.p;
	return output;
}

int main()
{
	String s1("Help!"), s2("Good!"), s3(s2), s4, s5;
	cout << "s1=" << s1 << endl;
	s3 = "Hello!";
	cout << "s3=" << s3 << endl;
	s3 = s2;
	cout << "s3=" << s3 << endl;
	s3 += s2;
	cout << "s3=" << s3 << endl;
	cin >> s4;
	cout << "s4=" << s4 << endl;
	s5 = s3 + s4;
	cout << "s5=" << s5 << endl;
	s5[0] = 'g';
	cout << "s5=" << s5 << endl;
	cout << "strlen(s5)=" << s5.Length() << endl;
	cout << boolalpha << (s3 == s1) << endl;
	cout << boolalpha << (s3 < s1) << endl;
	return 0;
}
